package co.edu.eam.ingsoft.jpa.reflect;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import co.edu.eam.ingsoft.jpa.annotations.Column;
import co.edu.eam.ingsoft.jpa.annotations.Entity;
import co.edu.eam.ingsoft.jpa.annotations.Id;
import co.edu.eam.ingsoft.jpa.annotations.Table;

public class EntityManager {

	private String path;

	public EntityManager(String path) {
		this.path = path;
	}

	public void persist(Object entity) {
		String tableName = path + File.separator + getTableName(entity)
				+ ".txt";
		String columns = getFieldId(entity) + File.pathSeparator
				+ getColumnsName(entity);
		String idValue = getIdValue(entity);
		String values = idValue + File.pathSeparator + getColumnsValues(entity);
		try {
			saveData(tableName, columns, values, idValue);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private String getTableName(Object entity) {
		Class<?> clazz = entity.getClass();

		String tableName = "";

		if (clazz.isAnnotationPresent(Entity.class)) {
			if (clazz.isAnnotationPresent(Table.class)) {
				Table table = clazz.getAnnotation(Table.class);
				tableName = table.name();
			}
			if (tableName.isEmpty()) {
				tableName = clazz.getSimpleName();
			}
		}
		return tableName;
	}

	private String getFieldId(Object entity) {
		Class<?> clazz = entity.getClass();

		String fieldId = "";

		Method[] methods = clazz.getDeclaredMethods();
		for (Method method : methods) {
			if (method.isAnnotationPresent(Id.class)) {
				fieldId = method.getName().substring(3, 4).toLowerCase()
						+ method.getName().substring(4);
				break;
			}
		}
		if (fieldId.isEmpty()) {
			Field[] fields = clazz.getDeclaredFields();
			for (Field field : fields) {
				if (field.isAnnotationPresent(Id.class)) {
					fieldId = field.getName();
					break;
				}
			}
		}
		return fieldId;
	}

	private String getIdValue(Object entity) {
		Class<?> clazz = entity.getClass();

		String idValue = "";

		Method[] methods = clazz.getDeclaredMethods();
		for (Method method : methods) {
			if (method.isAnnotationPresent(Id.class)) {
				try {
					idValue = method.invoke(entity).toString();
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				break;
			}
		}
		if (idValue.isEmpty()) {
			Field[] fields = clazz.getDeclaredFields();
			for (Field field : fields) {
				if (field.isAnnotationPresent(Id.class)) {
					idValue = field.getName();
					break;
				}
			}
			try {
				Method method = clazz.getMethod("get"
						+ idValue.substring(0, 1).toLowerCase()
						+ idValue.substring(1));
				idValue = method.invoke(entity).toString();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return idValue;
	}

	private String getColumnsName(Object entity) {
		Class<?> clazz = entity.getClass();

		String columns = "";

		Method[] methods = clazz.getDeclaredMethods();
		for (Method method : methods) {
			if (method.isAnnotationPresent(Column.class)) {
				Column column = method.getAnnotation(Column.class);
				columns += column.name() + File.pathSeparator;
				if (column.name().isEmpty()) {
					columns += method.getName().substring(3, 4).toLowerCase()
							+ method.getName().substring(4)
							+ File.pathSeparator;
				}
			}
			// else {
			// columns += method.getName().substring(3, 4).toLowerCase()
			// + method.getName().substring(4) + File.pathSeparator;
			// }
		}
		if (columns.isEmpty()) {
			Field[] fields = clazz.getDeclaredFields();
			for (Field field : fields) {
				if (field.isAnnotationPresent(Column.class)) {
					Column column = field.getAnnotation(Column.class);
					columns += column.name();
					if (column.name().isEmpty()) {
						columns += field.getName() + File.pathSeparator;
					}
				}
			}
		}
		return columns;
	}

	private String getColumnsValues(Object entity) {
		Class<?> clazz = entity.getClass();

		String values = "";

		Method[] methods = clazz.getDeclaredMethods();
		for (Method method : methods) {
			if (method.isAnnotationPresent(Column.class)) {
				try {
					values += method.invoke(entity) + File.pathSeparator;
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		return values;
	}

	private void saveData(String path, String columns, String values,
			String idValue) throws Exception {
		File file = new File(path).getAbsoluteFile();
		if (file.exists()) {
			BufferedReader reader = new BufferedReader(new FileReader(file));
			String linea = reader.readLine();
			Boolean isSaved = false;
			if (linea.startsWith(idValue)) {
				isSaved = true;
			} else {
				while (linea != null && !linea.isEmpty()) {
					if (linea.startsWith(idValue)) {
						isSaved = true;
						break;
					}
					linea = reader.readLine();
				}
			}
			reader.close();
			if (!isSaved) {
				PrintWriter writer = new PrintWriter(new FileWriter(file, true));
				writer.println(values);
				writer.close();
			}
		} else {
			file.createNewFile();
			PrintWriter writer = new PrintWriter(new FileWriter(file));
			writer.println(columns);
			writer.println(values);
			writer.close();
		}
	}
}
